/******************************************************************************
 * (C) Copyright 2013 Atech-Automotive
 * FILE NAME:    driver_e2.c
 * DESCRIPTION:
 * 
 * DATE BEGUN:   2015/08/14
 * BY:                         
 * PRODUCT NAME:
 * APPLICATION:
 * TARGET H/W:
 * DOC REF:
 *****************************************************************************
 */

/*****************************************************************************
** #include 
*****************************************************************************/
#include "system.h"
#include "driver_e2.h"
//#include "sys_clock_Cfg.h"

#include "hwa_e2_callback.h"

/*****************************************************************************
** #define
*****************************************************************************/
#define E2_WAIT_FOR_FINISH (FALSE)

#define E2_TIMEMAX      (26U)        /* 26ms Max */

/* 
**  EE_START_ADDR               
**  Description: the start address of EEPROM that will used for system 
**  S12G48 : 0x400~0x9FF, 1.5K 
**  S12G64 : 0x400~0x0BFF, 2 K 
**  S12G128: 0x400~0x13FF, 4 K 
**  S12G192: 0x400~0x13FF, 4 K 
*/

#define EE_START_ADDR  (0x0400) 


/*****************************************************************************
** typedef
*****************************************************************************/
typedef enum
{
    E2_IDLE      = 0U,
    E2_WAIT      = 1U,
    E2_ERASE     = 2U,
    E2_WAITERASE = 3U,
    E2_WRITE     = 4U,
    E2_WAITWRITE = 5U,
    E2_INI       = 6U

} EE_Status_E;

/*****************************************************************************
** global variable
*****************************************************************************/


/*****************************************************************************
** static variables
*****************************************************************************/
static UINT8 *p_u8_e2_status;
static EE_Status_E s_e2_status = E2_INI;

/*****************************************************************************
** static constants
*****************************************************************************/


/*****************************************************************************
** static function prototypes
*****************************************************************************/


/*****************************************************************************
** function prototypes
*****************************************************************************/


/****************************************************************************/
/****************************************************************************/
/**
 * Function Name: Driver_E2Init
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/08/14,                 
 ****************************************************************************/
void Driver_E2Init( void )
{
    while (!FSTAT_CCIF)
    {
        /* wait for FTM reset to complete */
    }

#if 0//(SYSTEM_BUS_CLOCK == CLK_8MHZ)    
    	  
    FCLKDIV = 7;         
      	       
#elif 1//(SYSTEM_BUS_CLOCK == CLK_16MHZ)
      
    FCLKDIV = 15;         
 
#else
    #error "MAC SYSTEM_BUS_CLOCK is NOT defined !"    /* system clock Defines not found! */   
#endif


}

/****************************************************************************/
/**
 * Function Name: Driver_E2EraseSectorDirect
 * Description: Erase 4 byte into the address in eeprom.
 *              1. Please the addr must be (addr % 4 == 0).
 *              2. Return False if want to WR user space.
 *              3. G128 that allowed be used: 0x400 - 0x11FF
 *              4. G48 that allowed be used: 0x400 - 0x7FF
 *
 * Param:   none
 * Return:  none
 * Author:  2016/03/31,                 
 ****************************************************************************/
#if 0
BOOL Driver_E2EraseSectorDirect( UINT16 addr )
{
    UINT32 Addr = 0x00;

    ///////////////////////////

    if( 0 != (addr % 4) )
    {
        return FALSE;
    }

    if( addr >= c_u16_e2_cfg_start_addr ) /* Don't WR user space */
    {
        return FALSE;
    }

    Addr += addr;

    while(FSTAT_CCIF == 0);  /* wait if command in progress */

    FSTAT = 0x30U;           /* Clear error flags */

    FCCOBIX = 0;
    FCCOBHI = 0x12;
    FCCOBLO = (byte)(((UINT32)Addr) >> 16);

    FCCOBIX++;
    FCCOB = (word)(((dword)Addr) & 0xFFFFFFFEUL); /* Low address word aligned to word*/

    FSTAT = 0x80U;

#if E2_WAIT_FOR_FINISH == TRUE
    while(FSTAT_CCIF == 0);       //wait if command in progress
#endif
}
#endif
/*****************************************************************************/
/**
 * Function Name: void Driver_E2EraseSector(UINT8 address)
 * Description:  erase a sector,4 bytes.
 *
 * Param:
 * Return:  none
 * Author:  none
 *****************************************************************************/
void Driver_E2EraseSector( UINT16 address, UINT8 *pStatus )
{
    UINT32 Addr = (UINT32)EE_START_ADDR;

    Addr += address;

    while(FSTAT_CCIF == 0);  /* wait if command in progress */

    FSTAT = 0x30U;           /* Clear error flags */

    *pStatus = E2_CMD_STARTED;

    FCCOBIX = 0;
    FCCOBHI = 0x12;
    FCCOBLO = (byte)(((UINT32)Addr) >> 16);

    FCCOBIX++;
    FCCOB = (word)(((dword)Addr) & 0xFFFFFFFEUL); /* Low address word aligned to word*/

    FSTAT = 0x80U;
    p_u8_e2_status = pStatus;
    s_e2_status   = E2_ERASE;
#if E2_WAIT_FOR_FINISH == TRUE
    while(FSTAT_CCIF == 0);       //wait if command in progress
#endif
}

#if 0
/****************************************************************************/
/**
 * Function Name: Driver_E2WriteDirect
 * Description: Write 4 byte into the address in eeprom.
 *              1. Please the addr must be (addr % 4 == 0).
 *              2. Return False if want to WR user space.
 *              3. G128 that allowed be used: 0x400 - 0x11FF
 *              4. G48 that allowed be used: 0x400 - 0x7FF
 *
 * Param:   none
 * Return:  TRUE  - operation success
 *          FALSE - operation failure
 * Author:  2015/12/03,                 
 ****************************************************************************/
BOOL hwa_e2WriteAddrDirect( UINT8 *pBuf, UINT16 addr )
{
    UINT8 EE_TMP[4];
    UINT32 PhraseAddr  = 0x00;

    ///////////////////////////////

    if( 0 != (addr % 4) )
    {
        return FALSE;
    }

    if( addr >= c_u16_e2_cfg_start_addr ) /* Don't WR user space */
    {
        return FALSE;
    }

    //-------------------------------------------------------------------------
    /* Save X Byte EEPROM's data In Ram */
    EE_TMP[0] = *pBuf;
    EE_TMP[1] = *(pBuf+1);
    EE_TMP[2] = *(pBuf+2);
    EE_TMP[3] = *(pBuf+3);

    PhraseAddr += addr;

    while(FSTAT_CCIF == 0);   /* wait if command in progress */
    
    FSTAT = 0x30U;            /* Clear error flags */

    FCCOBIX = 0;
    FCCOBHI = 0x11;
    FCCOBLO = (byte)(PhraseAddr >> 16U);

    FCCOBIX++;
    FCCOB = (word)PhraseAddr;          /* Low address word */

    FCCOBIX++;
    FCCOBHI = EE_TMP[0];
    FCCOBLO = EE_TMP[1];

    FCCOBIX++;
    FCCOBHI = EE_TMP[2];
    FCCOBLO = EE_TMP[3];

    FSTAT = 0x80U;

#if E2_WAIT_FOR_FINISH == TRUE
    while(FSTAT_CCIF == 0);     //wait if command in progress
#endif

    return TRUE;
}

#endif

/****************************************************************************/
/**
 * Function Name: Driver_E2Write
 * Description: 
 *
 * Param:   none
 * Return:  none
 * Author:  2014/08/04,                 
 ****************************************************************************/
void Driver_E2Write( UINT8 *pBuf, UINT16 addr, UINT8 nBytes, UINT8 *pStatus )
{
    UINT8 EE_TMP[8];
    UINT32 PhraseAddr  = EE_START_ADDR;

    ///////////////////////////////
    
    (void)nBytes;

    *pStatus   = E2_CMD_STARTED;

    //-------------------------------------------------------------------------
    /* Save X Byte EEPROM's data In Ram */
    EE_TMP[0] = *pBuf;
    EE_TMP[1] = *(pBuf+1);
    EE_TMP[2] = *(pBuf+2);
    EE_TMP[3] = *(pBuf+3);
    EE_TMP[4] = *(pBuf+4);
    EE_TMP[5] = *(pBuf+5);
    EE_TMP[6] = *(pBuf+6);
    EE_TMP[7] = *(pBuf+7);

    PhraseAddr += addr;

    while(FSTAT_CCIF == 0);   /* wait if command in progress */
    
    FSTAT = 0x30U;            /* Clear error flags */

    FCCOBIX = 0;
    FCCOBHI = 0x11;
    FCCOBLO = (byte)(PhraseAddr >> 16U);

    FCCOBIX++;
    FCCOB = (word)PhraseAddr;          /* Low address word */

    FCCOBIX++;
    FCCOBHI = EE_TMP[0];
    FCCOBLO = EE_TMP[1];

    FCCOBIX++;
    FCCOBHI = EE_TMP[2];
    FCCOBLO = EE_TMP[3];

    FCCOBIX++;
    FCCOBHI = EE_TMP[4];
    FCCOBLO = EE_TMP[5];

    FCCOBIX++;
    FCCOBHI = EE_TMP[6];
    FCCOBLO = EE_TMP[7];

    FSTAT = 0x80U;
    p_u8_e2_status = pStatus;
    s_e2_status   = E2_WRITE;
#if E2_WAIT_FOR_FINISH == TRUE
    while(FSTAT_CCIF == 0);     //wait if command in progress
#endif
}

/****************************************************************************/
/**
 * Function Name: Driver_E2Read
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2014/08/04,                 
 ****************************************************************************/
void Driver_E2Read( UINT8 *pBuf, UINT16 addr, UINT8 nBytes, UINT8 *pStatus )
{
    UINT32 value_addr = 0x00;
    UINT8  u8_tmp;

    value_addr = (UINT32)EE_START_ADDR + addr;

    while(FSTAT_CCIF == 0);

    for(u8_tmp = 0; u8_tmp < nBytes; u8_tmp++)
    {
        *(pBuf + u8_tmp) = *((far UINT8 *far)(value_addr + u8_tmp));
    }

    *pStatus = E2_CMD_DONE;
}

/****************************************************************************/
/**
 * Function Name: Driver_E2Monitor
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2014/08/04,                 
 ****************************************************************************/
void Driver_E2Monitor( void )
{
    static UINT8 s_e2_timer = E2_TIMEMAX;

    //////////////////////////////////

    if (s_e2_status != E2_IDLE)
    {
        switch (s_e2_status)
        {
        case E2_ERASE:
        case E2_WRITE:
             if ( FSTAT_CCIF == 1 ) /* operation finish */
             {                    
                 *p_u8_e2_status = E2_CMD_DONE; /* Cleared current command status */
                 s_e2_status     = E2_IDLE;
                 s_e2_timer      = E2_TIMEMAX;
             }
             else if( s_e2_timer == 1 )
             {
                 *p_u8_e2_status = E2_TIMEOUT;
 
                 s_e2_status = E2_IDLE;
             }
             if( s_e2_timer > 0 )
             {
                 s_e2_timer--;  /* time out count down */
             }
             break;
            
        case E2_INI:
             s_e2_status = E2_IDLE;
             break;
            
        default:
             break;
        }
    }
    else
    {
        s_e2_timer = E2_TIMEMAX;
    }
}

/*****************************************************************************
** End File
*****************************************************************************/

